/*
 *  Scene.h
 *  rayTracer
 *
 *  Created by Zachry Thayer on 10/6/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef _scene_h
#define _scene_h

#include <vector>
#include "Object.h"
#include "Light.h"
#include "Sphere.h"

#include "Vec3.h"
#include "Ray.h"

class Scene{
private:
	unsigned int w, h;
	unsigned int *buffer;//32bit framebuffer

	Vec3 pos, dir;
	
	int samples;//pow 2 or 1
	
	int reflectDepth;//how many times to recurse reflections

	bool emptyBackground;//make background translucent

	
	std::vector<Object*> objects;
	std::vector<Light*> lights;
	
	Intersect closestCollision(Ray &ray);
	
	void putColorBuf(int x, int y, unsigned int color);
	unsigned int getColorBuf(int x, int y);
	
	void saveImageTarga(const char* filename, unsigned int* data, int width, int height, int lineSize, int saveAlpha);
		
public:

	Scene(): pos(Vec3(0,0,-4.f)), dir(Vec3(0,0,360.f)){
		//w = 1920 * 2;
		//h = 2400;
		w = 800;
		h = 600;
		buffer = new unsigned int[w*h];
		for(int i = 0; i < w*h; i ++)
			buffer[i] = 0xDEADBEEF;
		
		samples = 1;
		
		reflectDepth = 5;
		
		emptyBackground = false;
		
	}
	
	Scene(Vec3 &position, Vec3 &direction,int width = 480, int height = 272, int sampleCount = 1, int reflectionDepth = 3, bool transparentBackground = false): pos(position), dir(direction){
		w = width;
		h = height;
		buffer = new unsigned int[w*h];
		for(int i = 0; i < w*h; i ++)
			buffer[i] = 0xDEADBEEF;
		
		samples = sampleCount;
		
		reflectDepth = reflectionDepth;
		
		emptyBackground = transparentBackground;

	}
	
	~Scene(){
		delete buffer;
	}
	
	int getWidth();
	int getHieght();
	void *getBuffer();
	int objectCount();
	int lightCount();
	
	int addObject(Object *o);//returns id
	int addLight(Light *l);//returns id
	void removeObject(int o);
	void removeLight(int l);
	
	void draw();//raytracing
	
	unsigned int trace(Ray &ray);
	unsigned int getBackground(Ray &ray);
	
	Vec3 getPosition();
	void setPosition(Vec3 &pos);
	void translate(Vec3 &trans);
	
	void saveRender(char *file);
	
};

/* tga header */
typedef struct
{
	unsigned char id_length;          /* size of image id */
	unsigned char colormap_type;      /* 1 is has a colormap */
	unsigned char image_type;         /* compression type */
	
	short	cm_first_entry;       /* colormap origin */
	short	cm_length;            /* colormap length */
	unsigned char cm_size;            /* colormap size */
	
	short	x_origin;             /* bottom left x coord origin */
	short	y_origin;             /* bottom left y coord origin */
	
	short	width;                /* picture width (in pixels) */
	short	height;               /* picture height (in pixels) */
	
	unsigned char pixel_depth;        /* bits per pixel: 8, 16, 24 or 32 */
	unsigned char image_descriptor;   /* 24 bits = 0x00; 32 bits = 0x80 */
	
} tga_header_t;

#define COLOR_R(c) (c &0xff)
#define COLOR_G(c) (c &0xff00)
#define COLOR_B(c) (c &0xff0000)
#define COLOR_A(c) (c &0xff000000)

#define COLOR_RF(c) ((c &0xff) / 255.f)
#define COLOR_GF(c) ((c >> 8 &0xff) / 255.f)
#define COLOR_BF(c) ((c >> 16 &0xff) / 255.f)
#define COLOR_AF(c) ((c >> 24 &0xff) / 255.f)

#define COLOR_RGBA(r,g,b,a) ((a & 0xff) << 24|(b & 0xff) << 16|(g & 0xff) << 8|(r & 0xff))
#define COLOR_RGBAF(r,g,b,a) (COLOR_RGBA((unsigned char)std::min(r*255.f,255.f),(unsigned char)std::min(g*255.f,255.f),(unsigned char)std::min(b*255.f,255.f),(unsigned char)std::min(a*255.f,255.f)))

#endif
